package ga.operadores.selecao;

import ga.base.Individuo;
import ga.base.OperadorSelecao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import problema.Solucao;
import util.MersenneTwister;

public class Roleta implements OperadorSelecao {

	@Override
	public List<Solucao> executar(List<Solucao> populacao, int tamanhoMaximo) {

		//Soma os fitness
		double qtdTotalFitness = 0;
		for(Solucao individuo : populacao){
			qtdTotalFitness = qtdTotalFitness + individuo.getFitness();
		}

		//Seta probabilidade de cada individuo e torna false caso individuo ja tenha sido selecionado em outras ocasioes
		for(Solucao solucao : populacao){
			Individuo individuo = (Individuo)solucao;
			double perc = individuo.getFitness()/ qtdTotalFitness;
			
			individuo.setRouletteFitness(new RouletteFitness());
			individuo.getRouletteFitness().setPercOfFitness(perc);
			individuo.getRouletteFitness().setSelecionado(false);
		}
		
		//Ordena por melhores percentuais de fitness
		Collections.sort(populacao);
		
		//Atribui ao melhor fitness o maior percentual e ao pior fitness o pior percentual
		int pos =0;
		for (int i = populacao.size()-1; i >= 0; i--) {
			double percCrescente = ((Individuo)populacao.get(pos)).getRouletteFitness().getPercOfFitness();
		    double percDescrescente = ((Individuo)populacao.get(i)).getRouletteFitness().getPercOfFitness();
		    
		    ((Individuo)populacao.get(pos)).getRouletteFitness().setPercOfFitness(percDescrescente);
		    ((Individuo)populacao.get(i)).getRouletteFitness().setPercOfFitness(percCrescente);
		    pos++;
		}

		//Sorteia numero de tamanho max e adiciona a qtd certa de individuo
		MersenneTwister random = new MersenneTwister();
		List<Solucao> novaPopulacao = new ArrayList<Solucao>();

		for (int i = 0; i < tamanhoMaximo; i++) {
			double somaDosPercDosIndividuos = 0;
			boolean adicionouIndividuoLista = false;
			int randomPerc = random.nextInt(100);

			while(!adicionouIndividuoLista){
				for(int j=0; j<populacao.size(); j++){
					Individuo individuo = (Individuo) populacao.get(j);
					somaDosPercDosIndividuos = somaDosPercDosIndividuos + individuo.getRouletteFitness().getPercOfFitness()*100;

					if(somaDosPercDosIndividuos >= randomPerc){
						if(individuo.getRouletteFitness().isSelecionado()){
							j=0;
							randomPerc = random.nextInt(100);
							somaDosPercDosIndividuos = 0;
						}else{
							novaPopulacao.add(individuo);
							individuo.getRouletteFitness().setSelecionado(true);
							adicionouIndividuoLista = true;
							break;
						}
					}
				}
			}
		}
		return novaPopulacao;
	}

	@Override
	public Individuo executar(List<Solucao> populacao) {
		// TODO Auto-generated method stub
		return null;
	}

}
